/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Copyright 2002-2003 by Mark Wolgemuth, All rights reserved.             */
/* Copyright 2002-2003 by Employease, Inc.  All rights reserved.           */
/*                                                                         */
/* Redistribution and use in source and binary forms, with or without      */
/* modification, are permitted provided that the following conditions      */
/* are met:                                                                */
/*                                                                         */
/*    1. Redistributions of source code must retain the above copyright    */
/* notice, this list of conditions and the following disclaimer.           */
/*    2. Redistributions in binary form must reproduce the above copyright */
/* notice, this list of conditions and the following disclaimer in the     */
/* documentation and/or other materials provided with the distribution.    */
/*                                                                         */
/* THIS SOFTWARE IS PROVIDED BY THE MOD_ATHENA PROJECT ``AS IS'' AND ANY   */
/* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE       */
/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR      */
/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR        */
/* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,   */
/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,     */
/* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR      */
/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY     */
/* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT            */
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   */
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.    */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "athd.h"

static apr_pool_t *_pool_mailq;
static apr_pool_t *_pool_mailq_tmp;
static ath_list *_mailq;
static pthread_mutex_t *_mail_mutex;

static int _athd_mail_queue_lock();
static int _athd_mail_queue_unlock();
static void * _athd_mail_thread_cleanup(void *ctx);

void *
athd_mail_thread(void *conf_ctx)
{
    int rv = APR_SUCCESS;
    athd_conf *conf = conf_ctx;
    char *exitmsg = "Mail Thread: Exited";
    int laststate, lasttype;
    struct sigaction action = { NULL } ;
    ASSERT(conf);
    
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &laststate);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &lasttype);
    pthread_cleanup_push((void *)_athd_mail_thread_cleanup, (void *)conf);

    action.sa_handler = athd_connection_reset;
    sigaction(SIGPIPE, &action, 0);

    athd_log(ATHD_INFO, "Mail Thread: Enter");
    while (!rv)
      {
	  ath_node *listctx;
	  pthread_testcancel();
	  ath_list_rewind_r(_mailq, &listctx);
	  while (ath_list_hasnext_r(_mailq, &listctx))
	    {
		athd_mail *mail = 
		  ath_list_popnext_r(_mailq, &listctx);
		pthread_testcancel();
		rv = athd_mail_send(conf, mail);
		/* what's the right apr status check for this? */
		if ((rv) && (rv != 70006))
		    athd_log(ATHD_CRIT, 
			     "Mail Thread: Error: [%d] %s (deleted)",
			     rv, (athd_err_str(_pool_mailq_tmp, rv)));
		else
		    athd_log(ATHD_DEBUG, "Mail Thread: Sent: Subject: %s",
			     mail->subject);
		athd_mail_destroy(&mail);
	    }
	  rv = APR_SUCCESS; /* for now, loop will never exit */
 	  apr_sleep(XTH_SEC(5)); /* 1/5 sec */
      }
    pthread_cleanup_pop(1);
}

void
athd_mail_queue_add(athd_mail *mail)
{
    ASSERT(mail);
    /* list add is already synced */
    /* must rm from list before destroy since node is alloced in obj pool */
    ath_list_ap_add_tail(mail->pool, _mailq, mail);
}

/* this must be run in single threaded context */
apr_status_t
athd_mail_thread_setup(apr_pool_t *pglobal)
{
    int rv = APR_SUCCESS;
    ASSERT(pglobal);
    apr_pool_create(&_pool_mailq, pglobal);
    apr_pool_create(&_pool_mailq_tmp, _pool_mailq);
    _mail_mutex = apr_pcalloc(_pool_mailq, sizeof(pthread_mutex_t));
    pthread_mutex_init(_mail_mutex, NULL);
    apr_pool_cleanup_register(_pool_mailq, _mail_mutex,
			      pthread_mutex_cleanup, apr_pool_cleanup_null);
    _mailq = ath_list_ap_alloc(_pool_mailq);
    return rv;
}

static int
_athd_mail_queue_lock()
{
    return pthread_mutex_lock(_mail_mutex);
}

static int
_athd_mail_queue_unlock()
{
    return pthread_mutex_unlock(_mail_mutex);
}

static void *
_athd_mail_thread_cleanup(void *ctx)
{
    athd_log(ATHD_INFO, "Mail Thread: Exit");
}

